/*!
 * \file amqp_comm9.c
 *
 * \brief rabbitmq amqp_0_9 数据包解析通用项
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 2.0
 * \author geyh
 * \date 2015/12/24
 *
 */
#include <stdio.h>

#include "frreport_comm.h"
#include "frbyte_buffer.h"
#include "amqp_basedata_type.h"

/*!
 * \ 1位长度位的字符串获取  带一字节类型说明
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ pp_out                     (char **         字符串出力)
 * \ i_flag_need                (int             是否需要数据)
 *
 * \return          FR_SUCC:成功\n
 *                  FR_FAIL:失败\n
 */
FR_STATIC int __amqp_get_short_str_0_9_0(Frbyte_Packet *p_st_data, char **pp_out, int i_flag_need)
{
    int i_ret = 0;
    unsigned int ui_str_len = 0;
    char *p_key = NULL;

    if(p_st_data == NULL || pp_out == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 1, &ui_str_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(ui_str_len == 0)
        return FR_SUCC;

    if(i_flag_need == FR_NO)
    {
        i_ret = bytebuff_skip (p_st_data, ui_str_len);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

        return FR_SUCC;
    }

    p_key = (char *)frmalloc (ui_str_len + 1);
    if(p_key == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_bytes (p_st_data, p_key, ui_str_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_key);
        return FR_FAIL;
    }

    p_key[ui_str_len] = '\0';

    if(*pp_out)
        frfree (*pp_out);

    *pp_out = p_key;

    return FR_SUCC;

}

/*!
 * \ 4位长度位的字符串获取   带一字节类型说明
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ pp_out                     (char **         字符串出力)
 * \ i_flag_need                (int             是否需要数据)
 *
 * \return          FR_SUCC:成功\n
 *                  FR_FAIL:失败\n
 */
FR_STATIC int __amqp_get_string_0_9_0(Frbyte_Packet *p_st_data, char **pp_out, int i_flag_need)
{
    int i_ret = 0;
    unsigned int ui_str_len = 0;
    char *p_str = NULL;
    uint8_t u8_type = 0;

    if(p_st_data == NULL || pp_out == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_char (p_st_data, &u8_type);
    if(i_ret == FR_FAIL || u8_type != 0x53)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, &ui_str_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(ui_str_len == 0)
        return FR_SUCC;

    if(i_flag_need == FR_NO)
    {
        i_ret = bytebuff_skip (p_st_data, ui_str_len);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

        return FR_SUCC;
    }

    p_str = (char *)frmalloc (ui_str_len + 1);
    if(p_str == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_bytes (p_st_data, p_str, ui_str_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_str);
        return FR_FAIL;
    }

    p_str[ui_str_len] = '\0';

    if(*pp_out)
        frfree (*pp_out);

    *pp_out = p_str;

    return FR_SUCC;

}

/*!
 * \ 4位长度位的字符串获取
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ pp_out                     (char **         字符串出力)
 * \ i_flag_need                (int             是否需要数据)
 *
 * \return          FR_SUCC:成功\n
 *                  FR_FAIL:失败\n
 */
FR_STATIC int __amqp_get_length_0_9_0(Frbyte_Packet *p_st_data, char **pp_out, int i_flag_need)
{
    int i_ret = 0;
    unsigned int ui_str_len = 0;
    char *p_str = NULL;

    if(p_st_data == NULL || pp_out == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, &ui_str_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(ui_str_len == 0)
        return FR_SUCC;

    if(i_flag_need == FR_NO)
    {
        i_ret = bytebuff_skip (p_st_data, ui_str_len);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

        return FR_SUCC;
    }

    p_str = (char *)frmalloc (ui_str_len + 1);
    if(p_str == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_bytes (p_st_data, p_str, ui_str_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_str);
        return FR_FAIL;
    }

    p_str[ui_str_len] = '\0';

    if(*pp_out)
        frfree (*pp_out);

    *pp_out = p_str;

    return FR_SUCC;

}

/*!
 * \ 1位长度位的字符串跳过  带一字节类型说明
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 *
 * \return          FR_SUCC:成功\n
 *                  FR_FAIL:失败\n
 */
FR_STATIC int __amqp_skip_short_str_0_9_0(Frbyte_Packet *p_st_data)
{
    int i_ret = 0;
    unsigned int ui_str_len = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 1, &ui_str_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, ui_str_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

/*!
 * \ 4位长度位的结构数据跳过  带一字节类型说明
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 *
 * \return          FR_SUCC:成功\n
 *                  FR_FAIL:失败\n
 */
FR_STATIC int __amqp_skip_struct_0_9_0(Frbyte_Packet *p_st_data)
{
    int i_ret = 0;
    unsigned int ui_str_len = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, &ui_str_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, ui_str_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

/*!
 * \ 跳过 指定长度
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 *
 * \return          FR_SUCC:成功\n
 *                  FR_FAIL:失败\n
 */
FR_STATIC int __amqp_skip_length_0_9_0(Frbyte_Packet *p_st_data)
{
    int i_ret = 0;
    unsigned int ui_str_len = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, &ui_str_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, ui_str_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

/*!
 * \ 判断是否为frame结尾
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
FR_STATIC int __amqp_frame_end_0_9_0(Frbyte_Packet *p_st_data)
{
    int i_ret = 0;
    uint8_t u8_tmp = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_get_char (p_st_data, &u8_tmp);
    if(i_ret == FR_FAIL || u8_tmp != 0xce)
        return FR_FAIL;

    return FR_SUCC;

}

/*!
 * \ connect start 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_connect_start_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0, i_loop = 7;
    char *p_key = NULL, *p_product = NULL, *p_version = NULL;
    char *p_server = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    //跳过长度
    i_ret = bytebuff_skip (p_st_data, 6);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    while (i_loop--)
    {
        i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_key, FR_YES);
        if(i_ret == FR_FAIL)
            goto ERROR;

        if(strcmp (p_key, "product") == 0)
        {
            i_ret =  __amqp_get_string_0_9_0 (p_st_data, &p_product, i_flag_need);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }
        else if(strcmp (p_key, "version") == 0)
        {
            i_ret = __amqp_get_string_0_9_0 (p_st_data, &p_version, i_flag_need);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }
        else
        {
            i_ret = __amqp_skip_struct_0_9_0 (p_st_data);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }

        frfree (p_key);
        p_key = NULL;

    }

    if(p_product && p_version)
    {
        p_server = (char *)frmalloc (strlen (p_product) + strlen (p_version) + 2);
        if(p_server == NULL)
            goto ERROR;

        snprintf (p_server, strlen (p_product) + strlen (p_version) + 2, "%s %s", p_product, p_version);
        frfree (p_product);
        frfree (p_version);
    }
    else if(p_product)
    {
        p_server = p_product;
        p_product = NULL;
    }
    else if(p_version)
    {
        frfree (p_version);
    }

    if(p_server)
    {
        if(p_st_session_private->p_server)
            frfree (p_st_session_private->p_server);

        p_st_session_private->p_server = p_server;
    }

    //Mechanisms: 504c41494e20414d51504c41494e
    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Locales: 656e5f5553
    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //ce 结尾
    i_ret = __amqp_frame_end_0_9_0(p_st_data);

    return i_ret;

ERROR:
    if(p_key)
        frfree (p_key);

    if(p_version)
        frfree (p_version);

    if(p_product)
        frfree (p_product);

    return FR_FAIL;
}

/*!
 * \ 获取用户名
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
FR_STATIC int __amqp_get_user(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_mechanism = NULL, *p_user = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_mechanism, FR_YES);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_mechanism && strcmp (p_mechanism, "PLAIN") == 0)
    {
        i_ret = __amqp_get_length_0_9_0 (p_st_data, &p_user, i_flag_need);
        if(i_ret == FR_FAIL)
        {
            frfree (p_mechanism);
            return FR_FAIL;
        }

        if(i_flag_need)
        {
            if(p_st_session_private->p_user_name)
                frfree (p_st_session_private->p_user_name);

            p_st_session_private->p_user_name = frstrdup (p_user + 1);
            if(p_st_session_private->p_user_name == NULL)
            {
                frfree (p_mechanism);
                frfree(p_user);
                return FR_FAIL;
            }
        }

        frfree (p_mechanism);

        if(p_user)
            frfree (p_user);

        return FR_SUCC;
    }
    else
    {
        //todo
    }

    if(p_mechanism)
        frfree (p_mechanism);

    return FR_FAIL;

}

/*!
 * \ connect start ok解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_connect_start_ok_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0, i_loop = 6;
    char *p_key = NULL, *p_product = NULL, *p_version = NULL;
    char *p_server = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
        p_st_session_private->i_flag_data_type = FRLOGIN_START;

    //跳过长度
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    while (i_loop--)
    {
        i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_key, FR_YES);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

        if(strcmp (p_key, "product") == 0)
        {
            i_ret =  __amqp_get_string_0_9_0 (p_st_data, &p_product, i_flag_need);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }
        else if(strcmp (p_key, "version") == 0)
        {
            i_ret = __amqp_get_string_0_9_0 (p_st_data, &p_version, i_flag_need);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }
        else
        {
            i_ret = __amqp_skip_struct_0_9_0 (p_st_data);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }

        frfree (p_key);
        p_key = NULL;

    }

    if(p_product && p_version)
    {
        p_server = (char *)frmalloc (strlen (p_product) + strlen (p_version) + 2);
        if(p_server == NULL)
            goto ERROR;

        snprintf (p_server, strlen (p_product) + strlen (p_version) + 2, "%s %s", p_product, p_version);
        frfree (p_product);
        frfree (p_version);
    }
    else if(p_product)
    {
        p_server = p_product;
        p_product = NULL;
    }
    else if(p_version)
    {
        frfree (p_version);
    }

    if(i_flag_need)
    {
        //服务版本协商
        if(p_st_session_private->p_server == NULL)
        {
            p_st_session_private->p_server = p_server;
        }
        else if(p_server && strcmp (p_st_session_private->p_server, p_server) > 0)
        {
            frfree (p_st_session_private->p_server);
            p_st_session_private->p_server = p_server;
        }
        else
        {
            if (p_server)
                frfree (p_server);
        }
    }

    //user
    i_ret = __amqp_get_user (p_st_data, p_st_body_data, p_st_session_private, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Locales: 656e5f5553
    i_ret = __amqp_skip_short_str_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //ce 结尾
    i_ret = __amqp_frame_end_0_9_0(p_st_data);

    return i_ret;

ERROR:
    if(p_key)
        frfree (p_key);

    if(p_version)
        frfree (p_version);

    if(p_product)
        frfree (p_product);


    return FR_FAIL;
}

/*!
 * \ connect close ok 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_connect_close_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    uint16_t u16_reply = 0;
    int i_ret = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    //reply code
    i_ret = bytebuff_get_short (p_st_data, 2, &u16_reply, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(i_flag_need)
    {
        switch (u16_reply)
        {
            case 403:
                p_st_session_private->i_flag_data_type = FRLOGIN_FAIL;
                break;

            case 200:
                p_st_session_private->i_flag_data_type = FRLOGOUT_START;
                break;

            default:
                break;

        }
    }

    i_ret = __amqp_skip_short_str_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}


/*!
 * \ queue declare 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_queue_declare_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_queue = NULL;
    st_amqp_private_data *p_st_private = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }

    //ticket
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //queue
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_queue, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_queue)
    {
        frfree (p_queue);
    }


    //flag
    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Arguments
    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ queue declare ok解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_queue_declare_ok_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_queue = NULL;
    st_amqp_private_data *p_st_private = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }
    //queue
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_queue, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //queue
    if(p_queue)
        frfree (p_queue);

    //message count  consumer count
    i_ret = bytebuff_skip (p_st_data, 8);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ exchange declare 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_exchange_declare_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_exchange = NULL, *p_type = NULL;
    st_amqp_private_data *p_st_private = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }

    //ticket
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //exchange
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_exchange, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_exchange)
        frfree (p_exchange);


    //type
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_type, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;


    if(p_type)
    {
        //类型 todo
        frfree (p_type);
    }

    //flag
    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Arguments
    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ exchange declare ok 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_exchange_declare_ok_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ queue bind 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_queue_bind_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_exchange = NULL, *p_queue = NULL, *p_routing = NULL;
    st_amqp_private_data *p_st_private = NULL;
    char arr_title[1024];

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
        p_st_private->i_flag_report = 1;
        p_st_private->is_message = 0;
    }


    //ticket
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //queue
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_queue, i_flag_need);
    if(i_ret == FR_FAIL)
        goto ERROR;

    //exchange
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_exchange, i_flag_need);
    if(i_ret == FR_FAIL)
        goto ERROR;

    //routing
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_routing, i_flag_need);
    if(i_ret == FR_FAIL)
        goto ERROR;

    //绑定关系
    if(p_exchange)
    {
        snprintf (arr_title, sizeof(arr_title), "SUB %s", p_exchange);
        i_ret = frreport_body_l7_add_str (p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title);
        if(i_ret == FR_FAIL)
            goto ERROR;

        i_ret = frreport_body_l7_add_str (p_st_body_data, "subscription.mq.topic", p_exchange);
        if(i_ret == FR_FAIL)
            goto ERROR;

        i_ret = frreport_body_l7_add_str (p_st_body_data, "subscription.mq.exchange", p_exchange);
        if(i_ret == FR_FAIL)
            goto ERROR;

        if(p_routing)
        {
            i_ret = frreport_body_l7_add_str (p_st_body_data, "subscription.mq.routing_key", p_routing);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }

        if(p_queue)
        {
            i_ret = frreport_body_l7_add_str (p_st_body_data, "subscription.mq.bind_queue", p_queue);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }

        if(p_st_private->p_exchange_type)
        {
            i_ret = frreport_body_l7_add_str (p_st_body_data, "subscription.mq.exchange_type", p_st_private->p_exchange_type);
            if(i_ret == FR_FAIL)
                goto ERROR;
        }

    }

    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        goto ERROR;

    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        goto ERROR;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        goto ERROR;

    if(p_queue)
        frfree (p_queue);

    if(p_exchange)
        frfree (p_exchange);

    if(p_routing)
        frfree (p_routing);

    return FR_SUCC;

ERROR:
    if(p_queue)
        frfree (p_queue);

    if(p_exchange)
        frfree (p_exchange);

    if(p_routing)
        frfree (p_routing);

    return FR_FAIL;

}

/*!
 * \ queue bind ok解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_queue_bind_ok_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ publish 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_basic_publish_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_routing_key = NULL, *p_exchange = NULL;
    st_amqp_private_data *p_st_private = NULL;
    char arr_title[1024];

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }

    //ticket
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //p_queue:
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_exchange, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_exchange)
    {
        snprintf (arr_title, sizeof (arr_title), "PUT %s", p_exchange);

        i_ret = frreport_body_l7_add_str (p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title);
        if(i_ret == FR_FAIL)
        {
            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "request.mq.topic", p_exchange);
        if(i_ret == FR_FAIL)
        {
            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "session.mq.topic", p_exchange);
        if(i_ret == FR_FAIL)
        {
            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "request.mq.exchange", p_exchange);
        if(i_ret == FR_FAIL)
        {
            frfree (p_exchange);
            return FR_FAIL;
        }

        p_st_private->p_exchange = p_exchange;

    }

    //Routing-Key: hello
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_routing_key, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_routing_key && p_st_private->p_exchange == NULL)
    {
        i_ret = frreport_body_l7_add_str (p_st_body_data, "request.mq.method", "PUT");

        if(i_ret == FR_FAIL)
        {
            frfree (p_routing_key);
            return FR_FAIL;
        }

        snprintf (arr_title, sizeof (arr_title), "PUT %s", p_routing_key);
        i_ret = frreport_body_l7_add_str (p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing_key);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "request.mq.queue", p_routing_key);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing_key);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "session.mq.queue", p_routing_key);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing_key);
            return FR_FAIL;
        }
    }

    if(p_routing_key)
    {
        i_ret = frreport_body_l7_add_str (p_st_body_data, "request.mq.routing_key", p_routing_key);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing_key);
            return FR_FAIL;
        }

        if(p_st_private->p_routing_key)
            frfree (p_st_private->p_routing_key);
        p_st_private->p_routing_key = p_routing_key;
        p_routing_key = NULL;
    }

    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

/*!
 * \ content header 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_content_header_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    //channel
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ content body 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_content_body_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    uint32_t u32_content_len = 0;
    char *p_content = NULL;
    st_amqp_private_data *p_st_private = NULL;
    char arr_filed_name[1024];

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }

    //channel
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, &u32_content_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(i_flag_need)
    {
//        if(p_st_private->i_use_request)
//            i_ret = frreport_body_l7_add_int (p_st_body_data, "request.mq.message.size", 1);
//        else
//            i_ret = frreport_body_l7_add_int (p_st_body_data, "notify.mq.message.size", 1);
//        if(i_ret == FR_FAIL)
//            return FR_FAIL;

        p_st_private->i_message_size++;
        p_content = (char *)frmalloc (u32_content_len + 1);
        if(p_content == NULL)
            return FR_FAIL;

        i_ret = bytebuff_get_bytes (p_st_data, p_content, u32_content_len);
        if(i_ret == FR_FAIL)
        {
            frfree (p_content);
            return FR_FAIL;
        }

        p_content[u32_content_len] = '\0';

        i_ret = fris_print_ascii(p_content, u32_content_len);
        if(i_ret == 0)
        {
            if(p_st_private->i_use_request)
                snprintf (arr_filed_name, sizeof (arr_filed_name), "request.mq.message.type.%d", p_st_private->i_message_size);
            else
                snprintf (arr_filed_name, sizeof (arr_filed_name), "notify.mq.message.type.%d", p_st_private->i_message_size);

            i_ret = frreport_body_l7_add_str (p_st_body_data, arr_filed_name, "binary");
            if(i_ret == FR_FAIL)
            {
                frfree (p_content);
                return FR_FAIL;
            }

            if(p_st_private->i_use_request)
                snprintf (arr_filed_name, sizeof (arr_filed_name), "request.mq.message.binary.%d", p_st_private->i_message_size);
            else
                snprintf (arr_filed_name, sizeof (arr_filed_name), "notify.mq.message.binary.%d", p_st_private->i_message_size);

            i_ret = frreport_body_l7_add_bin (p_st_body_data, arr_filed_name, p_content, u32_content_len);
            if(i_ret == FR_FAIL)
            {
                frfree (p_content);
                return FR_FAIL;
            }

        }
        else
        {
            if(p_st_private->i_use_request)
                snprintf (arr_filed_name, sizeof (arr_filed_name), "request.mq.message.type.%d", p_st_private->i_message_size);
            else
                snprintf (arr_filed_name, sizeof (arr_filed_name), "notify.mq.message.type.%d", p_st_private->i_message_size);

            i_ret = frreport_body_l7_add_str (p_st_body_data, arr_filed_name, "text");
            if(i_ret == FR_FAIL)
            {
                frfree (p_content);
                return FR_FAIL;
            }

            if(p_st_private->i_use_request)
                snprintf (arr_filed_name, sizeof (arr_filed_name), "request.mq.message.text.%d", p_st_private->i_message_size);
            else
                snprintf (arr_filed_name, sizeof (arr_filed_name), "notify.mq.message.text.%d", p_st_private->i_message_size);

            i_ret = frreport_body_l7_add_str (p_st_body_data, arr_filed_name, p_content);
            if(i_ret == FR_FAIL)
            {
                frfree (p_content);
                return FR_FAIL;
            }
        }

        frfree (p_content);
    }
    else
    {
        i_ret = bytebuff_skip (p_st_data, u32_content_len);
        if(i_ret == FR_FAIL)
            return FR_FAIL;
    }

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);
    return i_ret;

}

/*!
 * \ consumer 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_basic_consume_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_queue = NULL;
    st_amqp_private_data *p_st_private = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }

    //ticket
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //queue
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_queue, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //todo
    if(p_queue)
    {
        //根据bind 判断是否为topic  报sub信息
        frfree (p_queue);
    }

    //tag
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //filter
    i_ret = __amqp_skip_length_0_9_0 (p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ consumer ok 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_basic_consume_ok_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_consumer_tag = NULL;
    st_amqp_private_data *p_st_private = NULL;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;
    }

    //Consumer-Tag: amq.ctag-X9jfOzaUavK--K2ggDjNFA
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_consumer_tag, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_consumer_tag)
    {
        frfree (p_consumer_tag);
    }

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ basic deliver 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_basic_deliver_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    char *p_consumer_tag = NULL, *p_exchange = NULL, *p_routing = NULL;
    st_amqp_private_data *p_st_private = NULL;
    char arr_title[1024];

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    if(i_flag_need)
    {
        p_st_private = p_st_session_private->p_st_private;
        if(p_st_private == NULL)
            return FR_FAIL;

        if(p_st_private->i_message_size)
            i_flag_need = FR_NO;
    }


    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_consumer_tag, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_consumer_tag)
    {
//        if (p_st_private->p_consumer_tag == NULL || strcmp (p_st_private->p_consumer_tag, p_consumer_tag) != 0)
//        {
//            frfree (p_consumer_tag);
//            return FR_FAIL;
//        }

        frfree (p_consumer_tag);
    }

    //Delivery-Tag: 1
    i_ret = bytebuff_skip (p_st_data, 8);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //.... ...0 = Redelivered: False
    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Exchange: logs
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_exchange, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Routing-Key:
    i_ret = __amqp_get_short_str_0_9_0 (p_st_data, &p_routing, i_flag_need);
    if(i_ret == FR_FAIL)
    {
        if(p_exchange)
            frfree (p_exchange);
        return FR_FAIL;
    }

    if(p_exchange)
    {
        snprintf (arr_title, sizeof (arr_title), "NOTIFY %s", p_exchange);

        i_ret = frreport_body_l7_add_str (p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title);
        if(i_ret == FR_FAIL)
        {
            if (p_routing)
                frfree (p_routing);

            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "notify.mq.topic", p_exchange);
        if(i_ret == FR_FAIL)
        {
            if (p_routing)
                frfree (p_routing);

            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "session.mq.topic", p_exchange);
        if(i_ret == FR_FAIL)
        {
            if (p_routing)
                frfree (p_routing);

            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "notify.mq.exchange", p_exchange);
        if(i_ret == FR_FAIL)
        {
            if (p_routing)
                frfree (p_routing);

            frfree (p_exchange);
            return FR_FAIL;
        }

        frfree (p_exchange);

        if (p_routing)
        {
            i_ret = frreport_body_l7_add_str (p_st_body_data, "notify.mq.routing_key", p_routing);
            if(i_ret == FR_FAIL)
            {
                frfree (p_routing);
                return FR_FAIL;
            }

            frfree (p_routing);
        }
    }
    else if(p_routing)
    {
        snprintf (arr_title, sizeof (arr_title), "NOTIFY %s", p_routing);

        i_ret = frreport_body_l7_add_str (p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title);
        if(i_ret == FR_FAIL)
        {
            if (p_routing)
                frfree (p_routing);

            frfree (p_exchange);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "notify.mq.queue", p_routing);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "session.mq.queue", p_routing);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing);
            return FR_FAIL;
        }

        i_ret = frreport_body_l7_add_str (p_st_body_data, "notify.mq.routing_key", p_routing);
        if(i_ret == FR_FAIL)
        {
            frfree (p_routing);
            return FR_FAIL;
        }

        frfree (p_routing);
    }

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ 其他类型的结构 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ ui_len                     (结构长度)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_deflate_0_9_0(Frbyte_Packet *p_st_data, unsigned int ui_len)
{
    int i_ret = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, ui_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = __amqp_frame_end_0_9_0 (p_st_data);

    return i_ret;

}

/*!
 * \ method 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_method_parse_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, L7session_amqp_private *p_st_session_private, int i_flag_need)
{
    int i_ret = 0;
    unsigned int ui_len = 0;
    uint16_t u16_class = 0, u16_method = 0;

    if(p_st_data == NULL)
        return FR_FAIL;

    if(i_flag_need && (p_st_body_data == NULL || p_st_session_private == NULL))
        return FR_FAIL;

    //channel
    i_ret = bytebuff_skip (p_st_data, 2);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, &ui_len, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //class
    i_ret = bytebuff_get_short (p_st_data, 2, &u16_class, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //method
    i_ret = bytebuff_get_short (p_st_data, 2, &u16_method, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    ui_len -= 4;

    switch (u16_class)
    {
        //connect
        case 10:
            switch (u16_method)
            {
                //Start
                case 10:
                    i_ret = amqp_connect_start_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //Start-Ok
                case 11:
                    i_ret = amqp_connect_start_ok_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //connect open-ok
                case 41:
                    if(i_flag_need)
                        p_st_session_private->i_flag_data_type = FRLOGIN_SUCC;
                    i_ret = amqp_deflate_0_9_0(p_st_data, ui_len);
                    break;

                //connect close
                case 50:
                    i_ret = amqp_connect_close_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //connect close ok
                case 51:
                    if(i_flag_need)
                        p_st_session_private->i_flag_data_type = FRLOGOUT_END;
                    i_ret = amqp_deflate_0_9_0(p_st_data, ui_len);
                    break;

                default:
                    i_ret = amqp_deflate_0_9_0(p_st_data, ui_len);
                    break;
            }
            break;

        //exchange
        case 40:
            switch (u16_method)
            {
                //Declare
                case 10:
                    i_ret = amqp_exchange_declare_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //Declare-Ok
                case 11:
                    i_ret = amqp_exchange_declare_ok_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                default:
                    i_ret = amqp_deflate_0_9_0(p_st_data,ui_len);
                    break;
            }

            break;

        //queue
        case 50:
            switch (u16_method)
            {
                //Declare
                case 10:
                    i_ret = amqp_queue_declare_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //Declare-Ok
                case 11:
                    i_ret = amqp_queue_declare_ok_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //bind
                case 20:
                    i_ret = amqp_queue_bind_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //bind ok
                case 21:
                    i_ret = amqp_queue_bind_ok_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                default:
                    i_ret = amqp_deflate_0_9_0(p_st_data,ui_len);
                    break;
            }
            break;

        //basic
        case 60:
            switch (u16_method)
            {
                //Consume
                case 20:
                    i_ret = amqp_basic_consume_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //Consume-Ok
                case 21:
                    i_ret = amqp_basic_consume_ok_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //Publish
                case 40:
                    i_ret = amqp_basic_publish_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //deliver
                case 60:
                    i_ret = amqp_basic_deliver_0_9_0 (p_st_data,p_st_body_data,p_st_session_private,i_flag_need);
                    break;

                //其他
                default:
                    i_ret = amqp_deflate_0_9_0(p_st_data,ui_len);
                    break;
            }
            break;

        //其他不解析
        default:
            i_ret = amqp_deflate_0_9_0(p_st_data,ui_len);
            break;
    }

    return i_ret;

}

/*!
 * \ type 解析
 *
 * \ p_st_data                  (Frbyte_Packet * 入力数据)
 * \ p_st_body_data             (Frreport_body_data *      数据上报)
 * \ p_st_session_private       (L7session_amqp_private *  私有数据)
 * \ i_flag_need                (int                是否获取数据)
 *
 * \return          FR_SUCC:frame 结束\n
 *                  FR_FAIL:frame 未结束\n
 */
int amqp_parse_0_9_0(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, st_amqp_private_data *p_st_private, L7session_amqp_private *p_st_session_private)
{
    int i_ret = 0;
    unsigned int ui_version_major = 0, ui_version_minor = 0;
    unsigned int ui_type = 0, ui_all_len = 0;
    char arr_len[5];

    if(p_st_data == NULL || p_st_body_data == NULL || p_st_private == NULL || p_st_session_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    if(bytebuff_memstr (p_st_data, 0, 4, "AMQP", 4, &i_ret) == FR_SUCC)
    {
        i_ret = bytebuff_skip (p_st_data, 4);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        //protocol id
        i_ret = bytebuff_skip (p_st_data, 1);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        //version  0-9-1  只取前面大版本
        //major 0  或  1
        i_ret = bytebuff_get_int (p_st_data, 1, &ui_version_major, BYTE_BIG_ENDIAN);
        if(i_ret == FR_FAIL || ui_version_major != 0)
            return APM_L7_ANALYZE_FAIL;

        i_ret = bytebuff_get_int (p_st_data, 1, &ui_version_minor, BYTE_BIG_ENDIAN);
        if(i_ret == FR_FAIL || ui_version_minor != 9)
            return APM_L7_ANALYZE_FAIL;

        i_ret = bytebuff_skip (p_st_data, 1);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        return APM_L7_ANALYZE_SUCC;
    }

RESTART:
    //判断长度
    i_ret = bytebuff_get_bytes_at (p_st_data, bytebuff_getPosition (p_st_data) + 3, 4, arr_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_TODO;

    arr_len[4] = 0;
    ui_all_len = pntohi (arr_len);
    if(ui_all_len > p_st_data->ui_remaining)
        return APM_L7_ANALYZE_TODO;

     //TYPE
    i_ret = bytebuff_get_int (p_st_data, 1, &ui_type, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    p_st_private->i_flag_report = 0;
    p_st_private->is_message = 0;

    switch (ui_type)
    {
        case 1:
            i_ret = amqp_method_parse_0_9_0 (p_st_data, p_st_body_data, p_st_session_private, FR_YES);
            break;

        case 2:
            i_ret = amqp_content_header_0_9_0 (p_st_data, p_st_body_data, p_st_session_private, FR_YES);
            break;

        case 3:
            p_st_private->i_flag_report = 1;
            p_st_private->is_message = 1;
            i_ret = amqp_content_body_0_9_0 (p_st_data, p_st_body_data, p_st_session_private, FR_YES);
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    if(p_st_data->ui_remaining)
    {
        i_ret = bytebuff_truncate (p_st_data);
        if(i_ret == FR_FAIL)
            return FR_FAIL;
        goto RESTART;
    }

    if(p_st_private->i_message_size)
    {
        if(p_st_private->i_use_request)
            i_ret = frreport_body_l7_add_int (p_st_body_data, "request.mq.message.size", p_st_private->i_message_size);
        else
            i_ret = frreport_body_l7_add_int (p_st_body_data, "notify.mq.message.size", p_st_private->i_message_size);
        if(i_ret == FR_FAIL)
            return FR_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;

}


